#!/usr/bin/env python
# -*- coding: utf-8 -*-

import os
import sys
from collections import defaultdict
from pytools import mysqltool


def parse_record(string):
    counttype = ['InfoCount', 'UserCount']
    type_ = ['state1', 'uptype0', 'uptype1', 'uptype2']
    source = ['source0', 'source6', 'uptype0']
    source_again  = ['source0', 'source6']

    try:
        # catefirst1006_localfirst1096_source0_20130104_icount:1
        meta, v = string.split(':')
    except:
        # print 'string parse error:', string
        return None

    metalist = meta.split('_')

    i_u_count = metalist.pop(-1)

    # change the 'icount'(ucount) to 'InfoCount'() for backwards compatibility
    newtype2oldtype = dict(zip('icount ucount'.split(), counttype))
    try:
        k = newtype2oldtype[i_u_count]
    except:
        return None

    if len(metalist) == 2:  # A_20130104_ucount:601703
        if metalist[0] == 'A' and metalist[1].isdigit() and k in counttype:
            return [metalist[1], k, v]
        else:
            return None

    onetwothree = ['first', 'second', 'third']
    onetwo = onetwothree[:2]

    if metalist[0][4:first_digit(metalist[0])] not in onetwo or \
            metalist[1][5:first_digit(metalist[1])] not in onetwothree:
        return None

    if len(metalist) == 3:  # catefirst1006_localsecond464_20130104_icount:35
        if metalist[2].isdigit():
            return [metalist[0][4:], metalist[1][5:], k, v, metalist[2]]
    elif len(metalist) == 4:  # catefirst1006_localthird2671_state1_20130104_icount:46
        if metalist[2] in type_ and metalist[3].isdigit():
            return [metalist[0][4:], metalist[1][5:], metalist[2], k, v, metalist[3]]
    elif len(metalist) == 5:  # catefirst1006_localthird2743_state1_source0_20130104_icount:57
        if metalist[2] in type_ and metalist[3] in source and metalist[4].isdigit():
            return [metalist[0][4:], metalist[1][5:], metalist[2], metalist[3], k, v, metalist[4]]
    elif len(metalist) == 6:  # catefirst1006_localthird2743_state1_uptype0_source6_20130105_icount:68
        if metalist[2] in type_ and metalist[3] in source \
            and metalist[4] in source_again and metalist[-1].isdigit():
            return [metalist[0][4:], metalist[1][5:], metalist[2], metalist[3], metalist[4], k, v, metalist[4]]

    return None


def get_summary_fieldname():
    return ['stat_date', 'infos', 'users']


def get_detail_fieldname_index():
    fields = ['stat_date', 'dispcity1', 'dispcity2', 'dispcity3', 'belong_cate1', 'belong_cate2', 'total', 'total_user_count', 'state1', 'user_count', 'uptype0', 'new_info_users', 'uptype1', 'modify_info_users', 'uptype2', 'refresh_info_users', 'state1uptype0', 'new_valid_info_users', 'state1source0', 'ordinary_info_users', 'uptype0source0', 'ordinary_new_info_users', 'uptype1source0', 'ordinary_modify_info_users', 'uptype2source0', 'ordinary_refresh_users', 'state1uptype0source0', 'ordinary_new_valid_info_users', 'state1source6', 'vip_info_users', 'uptype0source6', 'vip_new_info_users', 'uptype1source6', 'vip_modify_info_users', 'uptype2source6', 'vip_refresh_info_users', 'state1uptype0source6', 'vip_new_valid_info_users']
    return dict(zip(fields, range(len(fields))))


def get_detail_fieldlen():
    return len(get_detail_fieldname_index())


def get_info(q):
    info = {}

    conn = mysqltool.connect_to_58_stats()
    r = mysqltool.query(conn, q)
    for one in r:
        info[one[0]] = one[1:]

    # print len(info)
    return info


def get_cate_level_upto_2():
    q = 'select cate_id, cate1, cate2 from belong_cate'
    return get_info(q)


def get_local_level_upto_3():
    q = 'select local_id, city1, city2, city3 from display_local'
    return get_info(q)


def first_digit(string):
    for i, a in enumerate(string):
        if a < '0' or a > '9':
            continue

        return i
    return -1


def get_cate_level(catestring, cateinfo):
    cateid = catestring[first_digit(catestring):]

    try:
        fullpath = cateinfo[cateid]
    except:
        # print 'count not get cate level info on:', catestring, cateid
        return None

    rt = ['0'] * 2
    for i, a in enumerate(fullpath):
        rt[i] = a
    return rt


def get_local_level(localstring, localinfo):
    for i, a in enumerate(localstring):
        if a < '0' or a > '9':
            continue
        localid = localstring[i:]
        break

    assert localid == localstring[first_digit(localstring):]

    try:
        fullpath = localinfo[localid]
    except:
        # print 'count not get local level info on:', localstring, localid
        return None

    rt = ['0'] * 3
    for i, a in enumerate(fullpath):
        rt[i] = a
    return rt


def set_value_by_string(string, record, detail, k):
    b = get_detail_fieldname_index()[string]
    if 'UserCount' in record:
        b += 1
    detail[k][b] = record[-2]


def compose_mysql_row(record, summary, detail, cateinfo, localinfo):
    if len(record) == 3:
        summary += record  # += even summary is [], yy
        return

    k = tuple(record[0:2])

    if k not in detail:
        catelevel = get_cate_level(record[0], cateinfo)
        locallevel = get_local_level(record[1], localinfo)
        if catelevel is None or locallevel is None:
            # print 'count not get local or cate info for:', record
            with open('cate-or-local-levle-lack.txt', 'ab') as f:
                f.write(','.join(record) + '\n')
            return

        detail[k] = ['0'] * get_detail_fieldlen()
        detail[k][get_detail_fieldname_index()['stat_date']] = record[-1]

        b = get_detail_fieldname_index()['belong_cate1']
        for i, a in enumerate(catelevel):
            detail[k][b+i] = a
        b = get_detail_fieldname_index()['dispcity1']
        for i, a in enumerate(locallevel):
            detail[k][b+i] = a

    if len(record) == 4:
        raise Exception('the len of 4 count not exits')
    elif len(record) == 5: # catefirst1006_localsecond464_20130104_icount:35
        string = 'total'
    elif len(record) == 6: # catefirst1006_localthird2671_state1_20130104_icount:46
        string = record[2]
    elif len(record) == 7: # catefirst1006_localthird2743_state1_source0_20130104_icount:57
        string = record[2] + record[3]
    elif len(record) == 8:  # catefirst1006_localthird2743_state1_uptype0_source6_20130105_icount:68
        string = record[2] + record[3] + record[4]

    set_value_by_string(string, record, detail, k)


def load_summary_to_mysql(summary, day):
    # print summary
    if not summary:
        return

    tablename = 'post_summary'

    fields = ['stat_date', 'infos', 'users']
    values = [summary[0]]

    tofind = ['InfoCount', 'UserCount']
    for count in tofind:
        if count in summary:
            values.append(summary[summary.index(count) + 1])
        else:
            values.append('0')

    dbh = mysqltool.connect_to_58_stats()
    #print 
    mysqltool.insertinto(dbh, tablename, fields, values)


def get_channel_info():
    q = 'select cate_id, table_prefix from belong_cate left join channel_define on belong_cate.channel_id = channel_define.channel_id'
    info = {}

    conn = mysqltool.connect_to_base_dicts()
    r = mysqltool.query(conn, q)
    for one in r:
        info[one[0]] = one[1]

    return info


def load_detail_to_mysql(detail, day):
    channel_info = get_channel_info()
    fds = {}
    for prefix in set(channel_info.values()):
        filename = 'data/%s-%s.txt' % (day, prefix)
        fds[prefix] = open(filename, 'wb')

    #print len(detail)
    for k, v in detail.items():
        try:
            f = fds[channel_info[k[0][first_digit(k[0]):]]]
        except:
            print 'dict index error'
            print k[0][first_digit(k[0]):]
            continue
        txt = ','.join(v) + '\n'
        f.write(txt)
    
    print 'test'
    for prefix, f in fds.items():
        f.close()
        filename = 'data/%s-%s.txt' % (day, prefix)
        tablename = prefix + '_post_detail'
        #print tablename,day
        #q = "delete form %s where stat_date=%s;"%(tablename,day)
        #cmdtxt = 'echo \'%s\' | mysql --auto-rehash -h10.5.20.16 -P58885 -u"ec_stat" -p"L#c8UM5RGh5C" -D dbwww58com_58_stats' % (q)
        #os.system(cmdtxt)
        
        loaddata = 'load data low_priority local infile "%s" into table %s fields terminated by ",";' % (filename, tablename)
        cmdtxt = 'echo \'%s\' | mysql --auto-rehash -h10.5.20.16 -P58885 -u"ec_stat" -p"L#c8UM5RGh5C" -D dbwww58com_58_stats' % (loaddata)
        #print cmdtxt
        os.system(cmdtxt)
        os.system('rm ' + filename)


if __name__ == '__main__':
    if len(sys.argv) != 2:
        print 'usage: %s day' % (sys.argv[0])
        sys.exit(1)

    day = sys.argv[1]
    # day = '20121220'

    # infile = 'data/hoho.txt'
    infile = 'data/' + day +'.txt'

    cateinfo = get_cate_level_upto_2()
    localinfo = get_local_level_upto_3()
    # print cateinfo
    # print localinfo

    summary = []
    detail = {}
    for line in open(infile, 'rb').readlines():
        record = parse_record(line.strip())
        if record is None:
            continue

        # print line.strip()
        # print record
        compose_mysql_row(record, summary, detail, cateinfo, localinfo)
    try:
        load_summary_to_mysql(summary, day)
    except Exception:
        pass
    
    load_detail_to_mysql(detail, day)
